﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing.Drawing2D;
using Noris.Tools.TraceVisualiser.Components;
using Noris.Tools.TraceVisualiser.Support;

namespace Noris.Tools.TraceVisualiser.Forms
{
    internal partial class AboutForm : DForm
    {
        public AboutForm()
        {
            this.InitializeComponent();
            this.ComponentInit();
            this.LoadServices();
        }
        private void ComponentInit()
        {
            this.CancelButton = this._OkButton;
            this.Paint += new PaintEventHandler(AboutForm_Paint);
            this._Line1.BackColor = Color.Transparent;
            this._Line2.BackColor = Color.Transparent;
            this._RtfText.BackColor = RealBackColor;
            string rtfText = @"{\rtf1\ansi\ansicpg1250\deff0\deflang1029{\fonttbl{\f0\froman\fprq2\fcharset238 Cambria;}}
{\*\generator Msftedit 5.41.15.1515;}\viewkind4\uc1\pard\b\f0\fs20 Asseco Solutions a.s.\b0 «Author»,\par
(c) 2013, \ul http://www.AssecoSolutions.eu\ulnone\par
}
 ";
            rtfText = rtfText.Replace("«Author»", (Steward.DebugMode ? @" && \i David Jan\'e1\'e8ek\i0 " : ""));
            this._RtfText.Rtf = rtfText;
            this._RtfText.LinkClicked += new LinkClickedEventHandler(_RtfText_LinkClicked);
            this._RtfText.GotFocus += new EventHandler(_RtfText_GotFocus);
            this._PicHelios.BackColor = RealBackColor;
            this.TransparencyKey = RealTransparentColor;
            this.BackColor = RealTransparentColor;
        }
        private void _RtfText_GotFocus(object sender, EventArgs e)
        {
            this._OkButton.Focus();
        }
        private void AboutForm_Paint(object sender, PaintEventArgs e)
        {
            GraphicsPath path = new GraphicsPath(FillMode.Winding);
            int x0 = 0;                // left
            int x1 = 3;                // left tangent
            int x4 = this.Width - 1;   // right
            int x2 = x4 / 2;           // X center
            int x3 = x4 - x1;          // right tangent

            int y0 = 0;                // top
            int y1 = 2;                // top tangent
            int y4 = this._OkButton.Top - 2;  // bottom
            int y2 = y4 / 2;           // Y center
            int y3 = y4 - y1;          // bottom tangent

            path.AddPolygon(new Point[] {
                        new Point(x1, y0),
                        new Point(x3, y0),
                        new Point(x4, y1), 
                        new Point(x4, y3),
                        new Point(x3, y4),
                        new Point(x1, y4),
                        new Point(x0, y3),
                        new Point(x0, y1),
                        new Point(x1, y0)});
            path.CloseFigure();

            e.Graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
            e.Graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
            e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;

            using (Brush brush = new SolidBrush(RealBackColor))
            using (Pen pen = new Pen(RealBackColor))
            {
                e.Graphics.FillPath(brush, path);
                e.Graphics.DrawPath(pen, path);
            }
        }
        private void _RtfText_LinkClicked(object sender, LinkClickedEventArgs e)
        {
            Steward.RunProcess(e.LinkText);
        }
        private void _OkButton_Click(object sender, EventArgs e)
        {
            this.Close();
        }
        private Color RealBackColor { get { return Color.Aquamarine; } }
        private Color RealTransparentColor { get { return Color.Turquoise; } }
        private void LoadServices()
        {
            this._ImageList.Images.Clear();
            this._ImageList.Images.Add(IMAGE_WARNING, Pics.PicLibrary16.Warning_16_FromFile);

            this._ListView.View = View.Details;
            this._ListView.FullRowSelect = true;
            this._ListView.ShowItemToolTips = true;
            this.ToolTip.IsBalloon = false;

            this._ListView.Columns.Clear();
            this._ListView.Columns.Add(new ColumnHeader() { Text = "Name", Width = 360, TextAlign = HorizontalAlignment.Left });
            this._ListView.Columns.Add(new ColumnHeader() { Text = "Assembly", Width = 160, TextAlign = HorizontalAlignment.Left });

            this._ListView.Groups.Clear();
            this._ListView.Groups.Add(GROUP_READER, "TraceReaders");
            this._ListView.Groups.Add(GROUP_SEARCH, "Search providers");
            this._ListView.Groups.Add(GROUP_FN_GLOBAL, "Global function");
            this._ListView.Groups.Add(GROUP_FN_CONTEXT, "Context function");

            this._ListView.Items.Clear();
            this.LoadServiceOne(typeof(TraceData.ITraceReader), GROUP_READER);
            this.LoadServiceOne(typeof(Interface.ISearchProvider), GROUP_SEARCH);
            this.LoadServiceOne(typeof(Interface.IFunctionGlobalProvider), GROUP_FN_GLOBAL);
            this.LoadServiceOne(typeof(Interface.IFunctionContextMenuItem), GROUP_FN_CONTEXT);
        }
        private void LoadServiceOne(Type type, string groupName)
        {
            List<Type> services = Steward.GetServiceTypeList(type).ToList();
            services.Sort(PluginTypeComparer);
            foreach (Type service in services)
            {
                object srv = null;

                // Chyby?
                bool correct = false;
                string error = null;
                try
                {
                    srv = System.Activator.CreateInstance(service);
                    correct = true;
                }
                catch (Exception exc)
                {
                    error = exc.Message;
                }

                // IPlugin.Active ?
                bool enabled = Steward.DebugMode;
                if (!enabled && srv != null)
                {
                    enabled = true;
                    
                    if (srv is Interface.IPlugin)
                    {
                        Interface.IPlugin plugin = srv as Interface.IPlugin;
                        if (plugin != null)
                            enabled = plugin.Active;
                    }
                }

                if (enabled)
                {
                    string name = service.Namespace + "." + service.Name;
                    string library = System.IO.Path.GetFileName(service.Module.Assembly.Location);
                    ListViewItem item = new ListViewItem(new string[] { name, library }) { Group = this._ListView.Groups[groupName] };
                    if (!correct)
                        item.ImageKey = IMAGE_WARNING;
                    if (error != null)
                        item.ToolTipText = error;

                    this._ListView.Items.Add(item);
                }
            }
        }
        private static int PluginTypeComparer(Type a, Type b)
        {
            int cmp;

            // Nejprve řadím podle souboru: nejprve DLL, pak EXE. DLL podle abecedy.
            string aFile = System.IO.Path.GetFileName(a.Module.Assembly.Location).ToLower();
            string aExtn = System.IO.Path.GetExtension(aFile);
            string bFile = System.IO.Path.GetFileName(b.Module.Assembly.Location).ToLower();
            string bExtn = System.IO.Path.GetExtension(bFile);
            // Soubory: nejprve DLL, pak EXE:
            cmp = aExtn.CompareTo(bExtn);
            if (cmp != 0) return cmp;
            // DLL: podle abecedy:
            cmp = aFile.CompareTo(bFile);
            if (cmp != 0) return cmp;

            // V rámci jedné DLL pak podle namespace + name:
            string aName = a.Namespace + "." + a.Name;
            string bName = b.Namespace + "." + b.Name;
            return aName.CompareTo(bName);
        }
        private const string GROUP_READER = "Reader";
        private const string GROUP_SEARCH = "SearchProvider";
        private const string GROUP_FN_GLOBAL = "FunctionGlobal";
        private const string GROUP_FN_CONTEXT = "FunctionContext";
        private const string IMAGE_WARNING = "Warning";
    }
}
